package de.kuttenmann.jflake;
/**
 * Note that the class Vector3D is designed as immutable! Changes of this property may have heavy
 * implications wherever Vector3D is used directly or indirectly.
 */
public class Vector3D
{
	public static final Vector3D ZERO = new Vector3D();

	private final double x;
	private final double y;
	private final double z;

	public Vector3D(double x, double y, double z)
	{
		this.x = x;
		this.y = y;
		this.z = z;
	}

	public Vector3D()
	{
		this(0.0, 0.0, 0.0);
	}

	public Vector3D(Vector3D other)
	{
		this(other.x, other.y, other.z);
	}

	public double getX()
	{
		return x;
	}

	public double getY()
	{
		return y;
	}

	public double getZ()
	{
		return z;
	}

	public Vector3D add(final Vector3D other)
	{
		return new Vector3D(this.x + other.x, this.y + other.y, this.z + other.z);
	}

	public Vector3D sub(final Vector3D other)
	{
		return new Vector3D(this.x - other.x, this.y - other.y, this.z - other.z);
	}

	public Vector3D scale(double scale)
	{
		return new Vector3D(this.x * scale, this.y * scale, this.z * scale);
	}

	public double dot(final Vector3D other)
	{
		return this.x * other.x + this.y * other.y + this.z * other.z;
	}

	public Vector3D cross(final Vector3D other)
	{
		return
			new Vector3D(
				this.y * other.z - this.z * other.y,
				this.z * other.x - this.x * other.z,
				this.x * other.y - this.y * other.x);
	}

	public double length()
	{
		return Math.sqrt(this.dot(this));
	}

	public Vector3D normalize()
	{
		return this.scale(1.0 / this.length());
	}

	@Override
	public String toString()
	{
		return String.format("[%.3f; %.3f; %.3f]", this.x, this.y, this.z);
	}
}
